package main

import (
	"fmt"
	"sync"
)

// map的并发读写问题
// 方案1：读写锁（RWMutex）实现
// 这种方案简单通用。核心思路：用`sync.RWMutex`（读写锁）保护内置 map，读操作加读锁（支持并发读），写操作加写锁（排他锁，同一时间只能一个写），平衡安全性和性能。
// RWMap 读写锁保护的线程安全map
type RWMap struct {
	mu sync.RWMutex
	m  map[int]string // 实际存储数据的map
}

// NewRWMap 新建线程安全map
func NewRWMap(size int) *RWMap {
	return &RWMap{
		m: make(map[int]string, size),
	}
}

// Get 读取key对应的值
func (rm *RWMap) Get(key int) (string, bool) {
	rm.mu.RLock()         // 读锁：并发读安全
	defer rm.mu.RUnlock() // 函数结束释放锁
	val, exist := rm.m[key]
	return val, exist
}

// Set 设置key-value
func (rm *RWMap) Set(key int, val string) {
	rm.mu.Lock() // 写锁：排他锁，防止并发写
	defer rm.mu.Unlock()
	rm.m[key] = val
}

// Delete 删除key
func (rm *RWMap) Delete(key int) {
	rm.mu.Lock()
	defer rm.mu.Unlock()
	delete(rm.m, key)
}

// Len 获取map长度
func (rm *RWMap) Len() int {
	rm.mu.RLock()
	defer rm.mu.RUnlock()
	return len(rm.m)
}

// 测试代码
func main() {
	rm := NewRWMap(10)

	// 并发写
	var wg sync.WaitGroup
	for i := 0; i < 5; i++ {
		wg.Add(1)
		go func(n int) {
			defer wg.Done()
			rm.Set(n, fmt.Sprintf("val_%d", n))
		}(i)
	}
	wg.Wait()

	// 并发读
	for i := 0; i < 5; i++ {
		wg.Add(1)
		go func(n int) {
			defer wg.Done()
			val, exist := rm.Get(n)
			if exist {
				fmt.Printf("key=%d, val=%s\n", n, val)
			}
		}(i)
	}
	wg.Wait()

	fmt.Println("map长度：", rm.Len()) // 输出：5
}
